//
//  AppController.m
//  MacHeliosSim
//
//  Created by Paul Thompson on 8/12/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "AppController.h"


@implementation AppController

-(void)awakeFromNib
{
	[buildNumber setStringValue:[@"MacHeliosSim v.1.1.0 b." stringByAppendingString: BUILD_NUMBER]];
	[fileContentsTempDisplay setString:dataFileContents];
	[beamEnergyField setFloatValue:168.0];
	[fieldStrengthField setDoubleValue:3.0];
	[beamMassField setIntValue:28];
	[beamSymbolField setStringValue:@"Si"];
	[targetMassField setIntValue:2];
	[targetSymbolField setStringValue:@"H"];
	[ejectileMassField setIntValue:1];
	[ejectileSymbolField setStringValue:@"H"];
	reactionAttributedString=[[NSMutableAttributedString alloc] initWithString: @"Reacssstion" ];
	
	kinematicsGraph = [(CPXYGraph *)[CPXYGraph alloc] initWithFrame:NSRectToCGRect([hostView bounds])]; 
	simGraph = [(CPXYGraph *)[CPXYGraph alloc] initWithFrame:NSRectToCGRect([hostView2 bounds])]; 
	CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
	[kinematicsGraph applyTheme:theme];
	[simGraph applyTheme:theme];
	
	[hostView setHostedLayer:kinematicsGraph];
	[hostView2 setHostedLayer:simGraph];
	
	[kinematicsGraph setPaddingLeft:0];
	[kinematicsGraph setPaddingTop:0];
	[kinematicsGraph setPaddingRight:0];
	[kinematicsGraph setPaddingBottom:0];
	
	//////TESTING
	
	kinematicsGraph.plotAreaFrame.paddingTop = 20.0;
	kinematicsGraph.plotAreaFrame.paddingBottom = 60.0;
	kinematicsGraph.plotAreaFrame.paddingLeft = 80.0;
	kinematicsGraph.plotAreaFrame.paddingRight = 20.0;
	kinematicsGraph.plotAreaFrame.cornerRadius = 10.0;
	
	/////////TESTING^
	[simGraph setPaddingLeft:0];
	[simGraph setPaddingTop:0];
	[simGraph setPaddingRight:0];
	[simGraph setPaddingBottom:0];
	
	simGraph.plotAreaFrame.paddingTop = 20.0;
	simGraph.plotAreaFrame.paddingBottom = 60.0;
	simGraph.plotAreaFrame.paddingLeft = 80.0;
	simGraph.plotAreaFrame.paddingRight = 20.0;
	simGraph.plotAreaFrame.cornerRadius = 10.0;
	
	
	// Setup scatter plot space
	//    CPXYPlotSpace *plotSpaceKin = (CPXYPlotSpace *)kinematicsGraph.defaultPlotSpace;
	plotSpaceKin = (CPXYPlotSpace *)kinematicsGraph.defaultPlotSpace;
	
	plotSpaceKin.allowsUserInteraction = YES;
    plotSpaceKin.delegate = self;
	
	//CPXYPlotSpace *plotSpaceSim = (CPXYPlotSpace *)simGraph.defaultPlotSpace;
	plotSpaceSim = (CPXYPlotSpace *)simGraph.defaultPlotSpace;
	
	plotSpaceSim.allowsUserInteraction = YES;
    plotSpaceSim.delegate = self;
	
    // Grid line styles
    CPLineStyle *majorGridLineStyleKin = [CPLineStyle lineStyle];
    majorGridLineStyleKin.lineWidth = 0.75;
    majorGridLineStyleKin.lineColor = [[CPColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75];
    
    CPLineStyle *minorGridLineStyleKin = [CPLineStyle lineStyle];
    minorGridLineStyleKin.lineWidth = 0.25;
    minorGridLineStyleKin.lineColor = [[CPColor whiteColor] colorWithAlphaComponent:0.1];    
	
	CPLineStyle *majorGridLineStyleSim = [CPLineStyle lineStyle];
	majorGridLineStyleSim.lineWidth = 0.75;
	majorGridLineStyleSim.lineColor = [[CPColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75];
	
	CPLineStyle *minorGridLineStyleSim = [CPLineStyle lineStyle];
	minorGridLineStyleSim.lineWidth = 0.25;
	minorGridLineStyleSim.lineColor = [[CPColor whiteColor] colorWithAlphaComponent:0.1];    
	//////////////    
	
	
    // Axes
	CPXYAxisSet *axisSetKin = (CPXYAxisSet *)kinematicsGraph.axisSet;
    CPXYAxis *xKin = axisSetKin.xAxis;
	
	CPConstraints theConstraints = {CPConstraintFixed,CPConstraintFixed};
	[xKin  setIsFloatingAxis:YES];
	[xKin setConstraints:theConstraints];
	
	xKin.labelingPolicy = CPAxisLabelingPolicyAutomatic;
    xKin.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
    xKin.minorTicksPerInterval = 4;
    xKin.preferredNumberOfMajorTicks = 9;
    xKin.majorGridLineStyle = majorGridLineStyleKin;
    xKin.minorGridLineStyle = minorGridLineStyleKin;
    xKin.labelOffset = 10.0;
	xKin.title = @"Lab Angle (°)";
	xKin.titleOffset = 30.0;
	
	
	// Label Simulation x axis with a fixed interval policy
	CPXYAxisSet *axisSetSim = (CPXYAxisSet *)simGraph.axisSet;
    CPXYAxis *xSim = axisSetSim.xAxis;
	
	[xSim  setIsFloatingAxis:YES];
	[xSim setConstraints:theConstraints];
	
	xSim.labelingPolicy = CPAxisLabelingPolicyAutomatic;
    xSim.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
    xSim.minorTicksPerInterval = 4;
    xSim.preferredNumberOfMajorTicks = 9;
    xSim.majorGridLineStyle = majorGridLineStyleKin;
    xSim.minorGridLineStyle = minorGridLineStyleKin;
    xSim.labelOffset = 10.0;
	xSim.title = @"Lab Angle (°)";
	xSim.titleOffset = 30.0;
	
	
	
	//////////
	
	// Label yKin with an automatic label policy. 
    CPXYAxis *yKin = axisSetKin.yAxis;
    
	yKin.isFloatingAxis = YES;
	yKin.constraints = theConstraints;
	
	yKin.labelingPolicy = CPAxisLabelingPolicyAutomatic;
    yKin.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
    yKin.minorTicksPerInterval = 4;
    yKin.preferredNumberOfMajorTicks = 9;
    yKin.majorGridLineStyle = majorGridLineStyleKin;
    yKin.minorGridLineStyle = minorGridLineStyleKin;
    yKin.labelOffset = 10.0;
	yKin.title = @"Lab Energy (MeV)";
	yKin.titleOffset = 55.0;
	
 
	
	
	// Label ySim with an automatic label policy. 
	CPXYAxis *ySim = axisSetSim.yAxis;
	
	[ySim setIsFloatingAxis:YES];
	[ySim setConstraints:theConstraints];
	
	ySim.labelingPolicy = CPAxisLabelingPolicyAutomatic;
	ySim.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
	ySim.minorTicksPerInterval = 4;
	ySim.preferredNumberOfMajorTicks = 9;
	ySim.majorGridLineStyle = majorGridLineStyleSim;
	ySim.minorGridLineStyle = minorGridLineStyleSim;
	ySim.labelOffset = 10.0;
	ySim.title = @"Lab Energy (MeV)";
	ySim.titleOffset = 55.0;
	
	
	
	
	////////////////// 
	
	// Set axes
    kinematicsGraph.axisSet.axes = [NSArray arrayWithObjects:xKin, yKin, nil];
	simGraph.axisSet.axes = [NSArray arrayWithObjects:xSim, ySim, nil];
	/////////
	
	
	
	// Create two plots that use bindings
	kinLinePlot = [[CPScatterPlot alloc] init];
    kinLinePlot.identifier = @"Kinematics Plot";
	kinLinePlot.dataLineStyle.miterLimit = 1.0;
	kinLinePlot.dataLineStyle.lineWidth = 3.0;
	kinLinePlot.dataLineStyle.lineColor = [CPColor blueColor];
    [kinematicsGraph addPlot:kinLinePlot];
	[kinLinePlot bind:CPScatterPlotBindingXValues toObject:kinController withKeyPath:@"arrangedObjects.x" options:nil];
	[kinLinePlot bind:CPScatterPlotBindingYValues toObject:kinController withKeyPath:@"arrangedObjects.y" options:nil];
	
	
	simLinePlot = [[CPScatterPlot alloc] init];
    simLinePlot.identifier = @"Bindings Plot";
	simLinePlot.dataLineStyle.miterLimit = 1.0;
	simLinePlot.dataLineStyle.lineWidth = 3.0;
	simLinePlot.dataLineStyle.lineColor = [CPColor blueColor];
    [simGraph addPlot:simLinePlot];
	[simLinePlot bind:CPScatterPlotBindingXValues toObject:simController withKeyPath:@"arrangedObjects.x" options:nil];
	[simLinePlot bind:CPScatterPlotBindingYValues toObject:simController withKeyPath:@"arrangedObjects.y" options:nil];
	
	
	////////////	  
	
    // Put an area gradient under the plot above
    NSString *pathToFillImage = [[NSBundle mainBundle] pathForResource:@"BlueTexture" ofType:@"png"];
    CPImage *fillImage = [CPImage imageForPNGFile:pathToFillImage];
    fillImage.tiled = YES;
    CPFill *areaGradientFill = [CPFill fillWithImage:fillImage];
	/// kinLinePlot.areaFill = areaGradientFill;
	// kinLinePlot.areaBaseValue = [[NSDecimalNumber one] decimalValue];
	
	//simLinePlot.areaFill = areaGradientFill;
	// simLinePlot.areaBaseValue = [[NSDecimalNumber one] decimalValue];
	
	
	
	// Add plot symbols
	CPLineStyle *symbolLineStyle = [CPLineStyle lineStyle];
	symbolLineStyle.lineColor = [CPColor blackColor];
	CPPlotSymbol *plotSymbol = [CPPlotSymbol ellipsePlotSymbol];
	plotSymbol.fill = [CPFill fillWithColor:[CPColor blueColor]];
	plotSymbol.lineStyle = symbolLineStyle;
    plotSymbol.size = CGSizeMake(10.0, 10.0);
	// kinLinePlot.plotSymbol = plotSymbol;
	//simLinePlot.plotSymbol = plotSymbol;
    
	// Auto scale the plot space to fit the plot data
    // Extend the y range by 10% for neatness
    [plotSpaceKin scaleToFitPlots:[NSArray arrayWithObjects:kinLinePlot, nil]];
	[plotSpaceSim scaleToFitPlots:[NSArray arrayWithObjects:simLinePlot,nil]];
    CPPlotRange *xRange = plotSpaceKin.xRange;
    CPPlotRange *yRange = plotSpaceKin.yRange;
    [yRange expandRangeByFactor:CPDecimalFromDouble(1.1)];
	[xRange expandRangeByFactor:CPDecimalFromDouble(1.1)];
	
	xRange = plotSpaceSim.xRange;
	yRange = plotSpaceSim.yRange;
	[yRange expandRangeByFactor:CPDecimalFromDouble(1.1)];
	[xRange expandRangeByFactor:CPDecimalFromDouble(1.1)];
	
	
	
	
	
	
	
	
	
}

- (id)init
{
	[super init];
	nuclideData = [[NuclideTable alloc] init];
	dataFileContents = [self readCSVFromFileAtPath:[self getPathForFileName:@"NuclideData" AndType:@"csv"]];
	[nuclideData fillWithData:dataFileContents];
	font = [NSFont systemFontOfSize:12.0];
	superScriptFont = [NSFont systemFontOfSize:10.0];
	whitespace = [NSCharacterSet whitespaceCharacterSet];
	reactionFieldStyle = [[NSMutableParagraphStyle alloc] init];
	[reactionFieldStyle setAlignment:NSCenterTextAlignment];
	logString = [[NSMutableString alloc]init];
	kinOutputProduct = [[NSMutableArray alloc] init];
	kinOutputEjectile= [[NSMutableArray alloc] init];
	
	id x = [NSDecimalNumber numberWithFloat:1.0];
	id y = [NSDecimalNumber numberWithFloat:1.0];
	[kinOutputProduct addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: x, @"x", y, @"y",nil]];
	[kinOutputProduct addObject:[NSMutableDictionary 
								 dictionaryWithObjectsAndKeys:
								 (id)[NSNumber numberWithFloat:2.0],@"x",
								 (id)[NSNumber numberWithFloat:2.0],@"y",nil]];
	[kinOutputEjectile addObject:[NSMutableDictionary 
								  dictionaryWithObjectsAndKeys:
								  (id)[NSNumber numberWithFloat:1.0],@"x",
								  (id)[NSNumber numberWithFloat:1.0],@"y",nil]];
	[kinOutputEjectile addObject:[NSMutableDictionary 
								  dictionaryWithObjectsAndKeys:
								  (id)[NSNumber numberWithFloat:2.0],@"x",
								  (id)[NSNumber numberWithFloat:2.0],@"y",nil]];
	kinController = [[NSArrayController alloc] init];
	[kinController setContent:kinOutputProduct];
	simController = [[NSArrayController alloc] init];
	[simController setContent:kinOutputEjectile];
	productKinData = [[NSMutableArray alloc] init];
	ejectileKinData = [[NSMutableArray alloc] init];
	
	theRoughSimulator = [[HeliosRoughSim alloc] init];
	
	return self;
}


- (IBAction)switchKinAxes:(id)sender
{
	NSButtonCell *selCell = [sender selectedCell]; 
#ifdef DEBUG
	NSLog(@"Selected cell is %d", [selCell tag]);
#endif
	CPXYAxisSet *axisSet = (CPXYAxisSet *)kinematicsGraph.axisSet;
    CPXYAxis *x = axisSet.xAxis;
	CPXYAxis *y = axisSet.yAxis;

	switch ([selCell tag]) {
		case 0:
		{
			[kinLinePlot bind:CPScatterPlotBindingXValues toObject:kinController withKeyPath:@"arrangedObjects.x" options:nil];
			[kinLinePlot bind:CPScatterPlotBindingYValues toObject:kinController withKeyPath:@"arrangedObjects.y" options:nil];
			[self updatePlotSpace:plotSpaceKin ForPlot:kinLinePlot];
			x.title =  @"Lab Angle (°)";
			y.title = @"Lab Energy (MeV)";
		}
			break;
		
		case 1:
		{
			[kinLinePlot bind:CPScatterPlotBindingYValues toObject:kinController withKeyPath:@"arrangedObjects.x" options:nil];
			[kinLinePlot bind:CPScatterPlotBindingXValues toObject:kinController withKeyPath:@"arrangedObjects.y" options:nil];
			[self updatePlotSpace:plotSpaceKin ForPlot:kinLinePlot];
			y.title =  @"Lab Angle (°)";
			x.title = @"Lab Energy (MeV)";
		}
			break;

		default:
			break;
	}
}


- (IBAction)switchKinPlots:(id)sender
{
	NSButtonCell *selCell = [sender selectedCell]; 
#ifdef DEBUG
	NSLog(@"Selected cell is %d", [selCell tag]);
#endif

	switch ([selCell tag]) {
		case 0:
			//if(! [kinController content] == kinOutputEjectile)
			{
				[kinController setContent:kinOutputEjectile];
				[self updatePlotSpace:plotSpaceKin ForPlot:kinLinePlot];
#ifdef DEBUG
				NSLog(@"Case 0");
#endif
			}
			break;
		case 1:
			//if(! [kinController content] == kinOutputProduct)
			{
				[kinController setContent:kinOutputProduct];
				[self updatePlotSpace:plotSpaceKin ForPlot:kinLinePlot];
#ifdef DEBUG
				NSLog(@"Case 1");
#endif
			}
			
			break;

		default:
#ifdef DEBUG
			NSLog(@"Default Triggered");
#endif
			
			break;
	}
}


- (IBAction)switchSimAxes:(id)sender
{
	NSButtonCell *selCell = [sender selectedCell]; 
#ifdef DEBUG
	NSLog(@"Selected cell is %d", [selCell tag]);
#endif
	CPXYAxisSet *axisSet = (CPXYAxisSet *)simGraph.axisSet;
    CPXYAxis *x = axisSet.xAxis;
	CPXYAxis *y = axisSet.yAxis;
	
	switch ([selCell tag]) {
		case 0:
		{
			[simLinePlot bind:CPScatterPlotBindingYValues toObject:simController withKeyPath:@"arrangedObjects.energy" options:nil];
			[simLinePlot bind:CPScatterPlotBindingXValues toObject:simController withKeyPath:@"arrangedObjects.distanceTraveled" options:nil];
			[self updatePlotSpace:plotSpaceSim ForPlot:simLinePlot];
			y.title =  @"Lab Energy (MeV)";
			x.title = @"Distance Traveled (cm)";
		}
			break;
			
		case 1:
		{
			[simLinePlot bind:CPScatterPlotBindingXValues toObject:simController withKeyPath:@"arrangedObjects.energy" options:nil];
			[simLinePlot bind:CPScatterPlotBindingYValues toObject:simController withKeyPath:@"arrangedObjects.distanceTraveled" options:nil];
			[self updatePlotSpace:plotSpaceSim ForPlot:simLinePlot];
			x.title =  @"Lab Energy (MeV)";
			y.title = @"Distance Traveled (cm)";

		}
			break;
			
		default:
			break;
	}
}


- (IBAction)switchSimPlots:(id)sender
{
	NSButtonCell *selCell = [sender selectedCell]; 
#ifdef DEBUG
	NSLog(@"Selected cell is %d", [selCell tag]);
#endif
	
	switch ([selCell tag]) {
		case 0:
		{
			[simController setContent:simOutputEjectile];
			[self updatePlotSpace:plotSpaceSim ForPlot:simLinePlot];
#ifdef DEBUG
			NSLog(@"Case 0");
#endif
		}
			break;
		case 1:
		{
			[simController setContent:simOutputProduct];
			[self updatePlotSpace:plotSpaceSim ForPlot:simLinePlot];
#ifdef DEBUG
			NSLog(@"Case 1");
#endif
		}
			
			break;
			
		default:
#ifdef DEBUG
			NSLog(@"Default Triggered");
#endif
			
			break;
	}	
}


- (NSString *)readCSVFromFileAtPath:(NSString *)thePath
{
	NSString *dataBuffer;
	dataBuffer = [NSString stringWithContentsOfFile:thePath];
#ifdef DEBUG
	NSLog(@"%@",dataBuffer);
#endif
	return dataBuffer;
	
}


- (IBAction)restoreTable:(id)sender
{
	[nuclideData clearArray];
	dataFileContents = [self readCSVFromFileAtPath:[self getPathForFileName:@"NuclideData" AndType:@"csv"]];
	[nuclideData fillWithData:dataFileContents];
	
}


- (NSString *)getPathForFileName:(NSString *)theName AndType:(NSString *)theType
{
	NSString *inFilePath = [[NSBundle mainBundle] pathForResource:theName ofType:theType];
	return inFilePath;
}

- (IBAction)processReaction:(id)sender
{
	
	myLittleReaction = [[Reaction alloc] initWithBeamEnergy:[beamEnergyField floatValue]
												AndBeamMass:[beamMassField intValue]
											  AndBeamSymbol:[[beamSymbolField stringValue] 
															 stringByTrimmingCharactersInSet:whitespace]
											  AndTargetMass:[targetMassField intValue]
											AndTargetSymbol:[[targetSymbolField stringValue]
															 stringByTrimmingCharactersInSet:whitespace]
											AndEjectileMass:[ejectileMassField intValue]
										  AndEjectileSymbol:[[ejectileSymbolField stringValue]
															 stringByTrimmingCharactersInSet:whitespace] 
											AndNuclideTable:nuclideData];
	
	beamNuclide = [myLittleReaction beamNuclide];
	targetNuclide = [myLittleReaction targetNuclide];
	ejectileNuclide = [myLittleReaction ejectileNuclide];
	productNuclide = [myLittleReaction productNuclide];
	
	[beamSymbolField setStringValue:[beamNuclide elementSymbol]];
	[targetSymbolField setStringValue:[targetNuclide elementSymbol]];
	[ejectileSymbolField setStringValue:[ejectileNuclide elementSymbol]];
	[productMassField setIntValue:[productNuclide nucleonCount]];
	[productSymbolField setStringValue:[productNuclide elementSymbol]];
	[qValueLabel setFloatValue:[myLittleReaction qValue]];
	[reactionField setAttributedStringValue:[self generateFormattedReactionString]];
	
	
	//[self processKinematics:self];
	//[self runHELIOSRoughSim:self];
}

- (NSMutableAttributedString *)generateFormattedReactionString
{
	NSUInteger beamNucleonCountStringSize = [[@""stringByAppendingFormat:@"%i",[beamNuclide nucleonCount]]length];
	NSUInteger beamSymbolStringSize = [[@""stringByAppendingFormat:@"%@",[beamNuclide elementSymbol]]length];
	NSUInteger targetNucleonCountStringSize = [[@""stringByAppendingFormat:@"%i",[targetNuclide nucleonCount]]length];
	NSUInteger targetSymbolStringSize = [[@""stringByAppendingFormat:@"%@",[targetNuclide elementSymbol]]length];
	NSUInteger ejectileNucleonCountStringSize = [[@""stringByAppendingFormat:@"%i",[ejectileNuclide nucleonCount]]length];
	NSUInteger ejectileSymbolStringSize = [[@""stringByAppendingFormat:@"%@",[ejectileNuclide elementSymbol]]length];
	NSUInteger productNucleonCountStringSize = [[@""stringByAppendingFormat:@"%i", [productNuclide nucleonCount]]length];
	
	//	This declaration produces something along the lines of "19O(2H,1H)20O", for example.
	NSString *reactionString = [[NSString alloc] initWithFormat:@"%i%@(%i%@,%i%@)%i%@",
								[beamNuclide nucleonCount],[beamNuclide elementSymbol],
								[targetNuclide nucleonCount],[targetNuclide elementSymbol],
								[ejectileNuclide nucleonCount],[ejectileNuclide elementSymbol],
								[productNuclide nucleonCount],[productNuclide elementSymbol]];
	
	NSMutableAttributedString *tempReactionAttributedString = [[NSMutableAttributedString alloc] initWithString: reactionString];
	
	[tempReactionAttributedString addAttribute:NSParagraphStyleAttributeName
										 value:reactionFieldStyle
										 range:NSMakeRange(0, [reactionString length])];
	[tempReactionAttributedString addAttribute:NSFontAttributeName
										 value:font
										 range:NSMakeRange(0, [reactionString length])];
	[tempReactionAttributedString addAttribute:NSSuperscriptAttributeName
										 value:[NSNumber numberWithInt:1]
										 range:NSMakeRange(0, beamNucleonCountStringSize)];
	[tempReactionAttributedString addAttribute:NSFontAttributeName
										 value:superScriptFont
										 range:NSMakeRange(0, beamNucleonCountStringSize)];
	[tempReactionAttributedString addAttribute:NSSuperscriptAttributeName
										 value:[NSNumber numberWithInt:1]
										 range:NSMakeRange(beamNucleonCountStringSize+beamSymbolStringSize+1,targetNucleonCountStringSize )];
	[tempReactionAttributedString addAttribute:NSFontAttributeName
										 value:superScriptFont
										 range:NSMakeRange(beamNucleonCountStringSize+beamSymbolStringSize+1,targetNucleonCountStringSize )];
	[tempReactionAttributedString addAttribute:NSSuperscriptAttributeName
										 value:[NSNumber numberWithInt:1]
										 range:NSMakeRange((beamNucleonCountStringSize+beamSymbolStringSize+1
															+targetNucleonCountStringSize+targetSymbolStringSize+1)
														   ,ejectileNucleonCountStringSize )];
	[tempReactionAttributedString addAttribute:NSFontAttributeName
										 value:superScriptFont
										 range:NSMakeRange((beamNucleonCountStringSize+beamSymbolStringSize+1
															+targetNucleonCountStringSize+targetSymbolStringSize+1)
														   ,ejectileNucleonCountStringSize )];
	
	[tempReactionAttributedString addAttribute:NSSuperscriptAttributeName
										 value:[NSNumber numberWithInt:1]
										 range:NSMakeRange((beamNucleonCountStringSize+beamSymbolStringSize+1
															+targetNucleonCountStringSize+targetSymbolStringSize+1
															+ejectileNucleonCountStringSize + ejectileSymbolStringSize+1)
														   ,productNucleonCountStringSize)];
	[tempReactionAttributedString addAttribute:NSFontAttributeName
										 value:superScriptFont
										 range:NSMakeRange((beamNucleonCountStringSize+beamSymbolStringSize+1
															+targetNucleonCountStringSize+targetSymbolStringSize+1
															+ejectileNucleonCountStringSize + ejectileSymbolStringSize+1)
														   ,productNucleonCountStringSize)];
	
	
	
	return tempReactionAttributedString;
}

-(IBAction)generateGraphs:(id)sender
{
	[self processKinematics:self];
	[self runHELIOSRoughSim:self];
}

- (IBAction)processKinematics:(id)sender
{
	
	//	This method should call the KinematicsCalculator alloc and initializers, and call
	//	the KinematicsCalculator method labEnergyForAngle: in order to fill an NSDictionary
	//	one item at a time with energy/angle pairs.  Then, the generateGraph method should
	//	be called to generate the graph. 
	
	theKinalculator = [[KinematicsCalculator alloc] initWithReaction:myLittleReaction];
	KinCalcReturnData *moreData;
	NSMutableArray *tempKinOutputEjectile =[[NSMutableArray alloc] init];
	NSMutableArray *tempKinOutputProduct = [[NSMutableArray alloc] init];
	NSMutableArray *tempEjectileKinData = [[NSMutableArray alloc] init];
	NSMutableArray *tempProductKinData = [[NSMutableArray alloc] init];
	NSString *tempLogString = [[NSString alloc]initWithString:@"Beginning Kinematics Calculations\n"];
	
	float angle = 0.0; 
	
	for(int x = 0; x <180;x++)
	{
		angle = ( ((float)(x))*pi/180.0);
		moreData = [theKinalculator labEjectileEnergyForAngle:angle];
		
		tempLogString = [tempLogString stringByAppendingFormat: @"Ejectile Energy for CM angle %f degrees, lab angle %f, is %f MeV\n",
						 [moreData cmAngleInDegrees],
						 [moreData labAngleInDegrees],
						 [moreData energy]];
		
		id x = [NSDecimalNumber numberWithFloat:[moreData labAngleInDegrees]];
		id y = [NSDecimalNumber numberWithFloat:[moreData energy]];
		[tempKinOutputEjectile addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: x, @"x", y, @"y",nil]];
		[tempEjectileKinData addObject:[[KinCalcReturnData alloc]initWithKinData:moreData]];

		// below is the INCORRECT way to add objects to the current array
		//[kinOutputEjectile addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: x, @"x", y, @"y",nil]];
		
		// and here is the CORRECT way to do it.
		//[kinController addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: x, @"x", y, @"y",nil]];
		
	}
	
	ejectileKinData = tempEjectileKinData;
	
	tempLogString = [tempLogString stringByAppendingFormat: @"\nEjectile max lab angle in degrees = %f\n\n",[moreData maxLabAngleInDegrees]];
	[self setLogString:[logString stringByAppendingString:tempLogString]];

	tempLogString = @"";
	
	for(int x = 0; x <180;x++)
	{
		angle = ( ((float)(x))*pi/180.0);
		moreData = [theKinalculator labProductEnergyForAngle:angle];
		
		tempLogString = [tempLogString stringByAppendingFormat: @"Product Energy for CM angle %f degrees, lab angle %f, is %f MeV\n",
						 [moreData cmAngleInDegrees],
						 [moreData labAngleInDegrees],
						 [moreData energy]];
		
		id x = [NSDecimalNumber numberWithFloat:[moreData labAngleInDegrees]];
		id y = [NSDecimalNumber numberWithFloat:[moreData energy]];
		[tempKinOutputProduct addObject:[NSMutableDictionary  dictionaryWithObjectsAndKeys: x, @"x", y, @"y",nil]];
		[tempProductKinData addObject:[[KinCalcReturnData alloc]initWithKinData:moreData]];
	
	}
	
	productKinData = tempProductKinData;
	tempLogString = [tempLogString stringByAppendingFormat:@"\nProduct max lab angle in degrees = %f\n\n",[moreData maxLabAngleInDegrees]];
	[self setLogString:[logString stringByAppendingString:tempLogString]];

	[self setKinOutputEjectile:tempKinOutputEjectile];
 //	kinOutputEjectile = tempKinOutputEjectile;
	[self setKinOutputProduct:tempKinOutputProduct];
//	kinOutputProduct = tempKinOutputProduct;
	
	[self switchKinPlots:kinPlotSwitcher];
	[self switchKinAxes:kinAxisSwitcher];
	[self updatePlotSpace:plotSpaceKin ForPlot:kinLinePlot];
	
}

- (void)updatePlotSpace:(CPPlotSpace *)thePlotSpace ForPlot:(CPPlot *)thePlot
{
	
	// Auto scale the plot space to fit the plot data
    // Extend the y range by 10% for neatness
    [thePlotSpace scaleToFitPlots:[NSArray arrayWithObjects:thePlot, nil]];
    CPPlotRange *xRange = [thePlotSpace xRange];
    CPPlotRange *yRange = [thePlotSpace yRange];
	double oldYLocation = CPDecimalDoubleValue([yRange location]);
	[yRange expandRangeByFactor:CPDecimalFromDouble(1.05)];
	//[yRange setLocation:CPDecimalFromDouble(oldYLocation)];
	[xRange expandRangeByFactor:CPDecimalFromDouble(1.05)];
	//[xRange setLocation:CPDecimalFromDouble(0.0)];
	
	
	
	
}


- (IBAction)runHELIOSRoughSim:(id)sender
{
	
	
#ifdef DEBUG
	NSLog(@"Entering the Unknown! Brace for IMPACT!!!");
#endif

	double theMagneticField = [fieldStrengthField doubleValue];

	theRoughSimulator = [[HeliosRoughSim alloc] initWithReaction:myLittleReaction];
	RoughSimReturnData *tempData;
	NSMutableArray *tempSimOutputEjectile =[[NSMutableArray alloc]init];
	NSMutableArray *tempSimOutputProduct = [[NSMutableArray alloc]init];
	
	NSMutableDictionary *tempDict;
	NSString *tempString= [[NSString alloc]initWithString:@"Beginning Rough Simulation\n\n"];
	for(KinCalcReturnData *tempKinData in ejectileKinData)
	{
#ifdef DEBUG
		NSLog(@"Itterating");
#endif
		tempData = [theRoughSimulator labEjectileDistanceForKinCalcData:tempKinData 
													   AndFieldStrength:theMagneticField];
		tempString = [tempString stringByAppendingFormat:@"Ejectile-> E(MeV): %f V(m/s): %f V‖(m/s): %f CM∠(°): %f Lab∠(°): %f maxLab∠(°): %f distance: %f ω: %f field: %f\n",
							[tempData energy],
							[tempData velocity],
							[tempData vPerp],
							[tempData cmAngleInDegrees],
							[tempData labAngleInDegrees],
							[tempData maxLabAngleInDegrees],
							[tempData distanceTraveled],
							[tempData cyclotronFrequency],
							[tempData fieldStrength] ];
		
		id tempEnergy = [NSDecimalNumber numberWithDouble:tempData.energy];
		id tempCmAngle = [NSDecimalNumber numberWithDouble:tempData.cmAngle];
		id tempLabAngle = [NSDecimalNumber numberWithDouble:tempData.labAngle];
		id tempMaxLabAngle = [NSDecimalNumber numberWithDouble:tempData.maxLabAngle];
		id tempDistance = [NSDecimalNumber numberWithDouble:tempData.distanceTraveled];
		id tempCyclotronFrequency = [NSDecimalNumber numberWithDouble:tempData.cyclotronFrequency];
		id tempFieldStrength = [NSDecimalNumber numberWithDouble:tempData.fieldStrength];
		id tempCmAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData cmAngleInDegrees]];
		id tempLabAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData labAngleInDegrees]];
		id tempMaxLabAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData maxLabAngleInDegrees]];
		
		tempDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
					tempEnergy,@"energy",
					tempCmAngle,@"cmAngle",
					tempLabAngle,@"labAngle",
					tempMaxLabAngle,@"maxLabAngle",
					tempDistance,@"distanceTraveled",
					tempCyclotronFrequency,@"cyclotronFrequency",
					tempFieldStrength,@"fieldStrength",
					tempCmAngleInDegrees,@"cmAngleInDegrees",
					tempLabAngleInDegrees,@"labAngleInDegrees",
					tempMaxLabAngleInDegrees,@"maxLabAngleInDegrees",
					nil];
		
		[tempSimOutputEjectile addObject:tempDict];
	}
	
	[self setLogString:[logString stringByAppendingString: tempString]];
	tempString = @"\n";
	
	for(KinCalcReturnData *tempKinData in productKinData)
	{
		tempData = [theRoughSimulator labProductDistanceForKinCalcData:tempKinData 
													   AndFieldStrength:theMagneticField];
		tempString = [tempString stringByAppendingFormat:@"Product-> E(MeV): %f V(m/s): %f V‖(m/s): %f CM∠(°): %f Lab∠(°): %f maxLab∠(°): %f distance: %f ω: %f field: %f\n",
							[tempData energy],
							[tempData velocity],
							[tempData vPerp],
							[tempData cmAngleInDegrees],
							[tempData labAngleInDegrees],
							[tempData maxLabAngleInDegrees],
							[tempData distanceTraveled],
							[tempData cyclotronFrequency],
							[tempData fieldStrength] ];
		
		
		id tempEnergy = [NSDecimalNumber numberWithDouble:tempData.energy];
		id tempCmAngle = [NSDecimalNumber numberWithDouble:tempData.cmAngle];
		id tempLabAngle = [NSDecimalNumber numberWithDouble:tempData.labAngle];
		id tempMaxLabAngle = [NSDecimalNumber numberWithDouble:tempData.maxLabAngle];
		id tempDistance = [NSDecimalNumber numberWithDouble:tempData.distanceTraveled];
		id tempCyclotronFrequency = [NSDecimalNumber numberWithDouble:tempData.cyclotronFrequency];
		id tempFieldStrength = [NSDecimalNumber numberWithDouble:tempData.fieldStrength];
		id tempCmAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData cmAngleInDegrees]];
		id tempLabAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData labAngleInDegrees]];
		id tempMaxLabAngleInDegrees = [NSDecimalNumber numberWithDouble:[tempData maxLabAngleInDegrees]];
		
		tempDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
					tempEnergy,@"energy",
					tempCmAngle,@"cmAngle",
					tempLabAngle,@"labAngle",
					tempMaxLabAngle,@"maxLabAngle",
					tempDistance,@"distanceTraveled",
					tempCyclotronFrequency,@"cyclotronFrequency",
					tempFieldStrength,@"fieldStrength",
					tempCmAngleInDegrees,@"cmAngleInDegrees",
					tempLabAngleInDegrees,@"labAngleInDegrees",
					tempMaxLabAngleInDegrees,@"maxLabAngleInDegrees",
					nil];
		
		[tempSimOutputProduct addObject:tempDict];
	}
	
	[self setLogString:[logString stringByAppendingString: tempString]];
	
	[self setSimOutputEjectile: tempSimOutputEjectile];
//	simOutputEjectile = tempSimOutputEjectile;
	[self setSimOutputProduct:tempSimOutputProduct];
//	simOutputProduct = tempSimOutputProduct;
	
	[simController setContent:simOutputEjectile];
	[self switchSimPlots:simPlotSwitcher];
	[self switchSimAxes:simAxisSwitcher];
	
	
}



//	Not implimented at this time
- (IBAction)runHELIOSFullSim:(id)sender
{
#ifdef DEBUG
	NSLog(@"Entering the SUPER Unknown! Brace for IMPACT!!!");
#endif
}



- (void)setUpGraph:(CPGraph *)theGraph
{
}

@synthesize dataFilePath, dataFileContents;
@synthesize nuclideData;
@synthesize beamNuclide, targetNuclide, ejectileNuclide, productNuclide;
@synthesize myLittleReaction;
@synthesize simOutputProduct, simOutputEjectile, kinOutputProduct, kinOutputEjectile;
@synthesize theKinalculator;
@synthesize xShiftKin, yShiftKin,labelRotation,xShiftSim,yShiftSim;
@synthesize logString;
@synthesize kinController, simController;

@end
